package org.misty.practices.threadpool;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

/**
 * @author Misty on 2020-06-12
 */
public class ForkJoinPoolSample01 {
    static final CountDownLatch countDownLatch = new CountDownLatch(100);
    static final AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException, ExecutionException {


        TimeUnit.SECONDS.sleep(5);

        ForkJoinPool executor = new ForkJoinPool(10, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, false, 10, 11, 1, null, Integer.MAX_VALUE, TimeUnit.MILLISECONDS);

        ForkJoinPool executor2 = new ForkJoinPool(10);

        ForkJoinTask<Void> submit = executor.submit(new MainTask());
        submit.get();
    }

    static class MainTask extends RecursiveAction {
        @Override
        protected void compute() {
            List<DelayTask> list = new ArrayList<>(200);
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) {
                DelayTask task = new DelayTask();
                list.add(task);
                task.fork();
            }
            for (DelayTask task : list) {
                task.join();
            }
            long endTime = System.currentTimeMillis();
            System.out.println(endTime - startTime);
        }
    }

    static class DelayTask extends RecursiveAction {
        @Override
        protected void compute() {
            int id = counter.incrementAndGet();
            System.out.println("start " + id);
            try {
                Sleeper sleeper = new Sleeper(1000);
                ForkJoinPool.managedBlock(sleeper);
//                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("end " + id);
//            countDownLatch.countDown();
        }
    }


    static class Sleeper implements ForkJoinPool.ManagedBlocker {
        private final long until;

        public Sleeper(long timeInMills) {
            this.until = System.currentTimeMillis() + timeInMills;
        }

        public boolean isReleasable() {
            return System.currentTimeMillis() >= until;
        }

        public boolean block() {
            while (!isReleasable()) {
                LockSupport.parkUntil(until);
            }
            return true;
        }

    }
}
